package dieciLuglio;

import java.io.*;
import java.net.*;
import java.sql.*;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Properties;
import java.util.Random;
import java.util.StringTokenizer;

public class ServerRisto {
	
	private static Statement stat;
	static BufferedReader in=null; 
	static PrintWriter out=null;
	private static Connection conn;
	
	private static int importoDaPagare;
	
	private static Utente s;
	
	private static GregorianCalendar data=new GregorianCalendar();
	
	private static int idTavolo;
	
	
	
	public static void main(String [] args){
		try{
			ServerSocket server = new ServerSocket(3001);
			System.out.println("server partito");
			while(true){
			System.out.println("in attesa di connesioni");
			Socket client=server.accept();
			
			InputStreamReader isr = new InputStreamReader(client.getInputStream());
			in = new BufferedReader(isr);
			
			System.out.println("connessione effettuata");
			ObjectOutputStream output = new ObjectOutputStream (client.getOutputStream());

			String  str = in.readLine();
			StringTokenizer stk=new StringTokenizer(str);
			String metodo=stk.nextToken();
			
			if(metodo.equals("datiPiatti")){
				LinkedList<Alimento> ll=datiPiatti(stk.nextToken());
				output.writeObject(ll);
			}
			else if(metodo.equals("creaAlimento")){
				int valore=Integer.parseInt(stk.nextToken());
				Alimento a=(Alimento)creaAlimento(valore);
				output.writeObject(a);
			}
			else if (metodo.equals("accendiTavolo")){
				int codiceTav=Integer.parseInt(stk.nextToken());
				boolean eseguito=accendiTavolo(codiceTav);
				output.writeObject(eseguito);
			}
			else if (metodo.equals("spegniTavolo")){
				int codiceTav=Integer.parseInt(stk.nextToken());
				boolean eseguito=spegniTavolo(codiceTav);
				output.writeObject(eseguito);
			}
			else if(metodo.equals("inviaOrdine")){
				int lunghezza=Integer.parseInt(stk.nextToken());
				String lista=" ";
				for(int i=0;i<lunghezza;i++){
					lista+=stk.nextToken()+" ";
				}
				boolean eseguito=inviaOrdine(lunghezza,lista);
				output.writeObject(eseguito);
			}
			else if(metodo.equals("valuta")){
				int codice=Integer.parseInt(stk.nextToken());
				int voto=Integer.parseInt(stk.nextToken());
				boolean eseguito=valuta(codice,voto);
				output.writeObject(eseguito);
			}
			else if(metodo.equals("getValoriValutazione")){
				int codice=Integer.parseInt(stk.nextToken());
				double [] d=getValoriValutazione(codice);
				output.writeObject(d);
			}
			else if(metodo.equals("CostruisciMenu")){
				String nomeMenu=stk.nextToken();				
				LinkedList<Alimento>z=CostruisciMenu(nomeMenu);
				output.writeObject(z);
			}
			else if(metodo.equals("RandomMenu")){		
				LinkedList<Alimento>z=RandomMenu();
				output.writeObject(z);
			}
			else if(metodo.equals("contaPiatto")){	
				String piatto=stk.nextToken();
				int s=contaPiatto(piatto);
				output.writeObject(s);
			}
			else if(metodo.equals("contaQuantiMenu")){	
				int s=contaQuantiMenu();
				output.writeObject(s);
			}
			else if(metodo.equals("getNumeroPosti")){	
				int idTavolo=Integer.parseInt(stk.nextToken());
				int s=getNumeroPosti(idTavolo);
				output.writeObject(s);
			}
			else if(metodo.equals("getImportoDaPagare")){	
				int idTavolo=Integer.parseInt(stk.nextToken());
				double s=getImportoDaPagare(idTavolo);
				output.writeObject(s);
			}
			else if(metodo.equals("getCodiceU")){	
				String piatto=stk.nextToken();
				int s=getCodiceU(piatto);
				output.writeObject(s);
			}
			else if(metodo.equals("dissociaUtenteTavolo")){	
				int idTavolo=Integer.parseInt(stk.nextToken());
				boolean s=dissociaUtenteTavolo(idTavolo);
				output.writeObject(s);
			}
			else if(metodo.equals("associaUtenteATavolo")){	
				String nick=stk.nextToken();
				int idTavolo=Integer.parseInt(stk.nextToken());
				boolean s=associaUtenteATavolo(nick,idTavolo);
				output.writeObject(s);
			}
			else if(metodo.equals("getIdUtenteTavolo")){
				int idTavolo=Integer.parseInt(stk.nextToken());
				int s=getIdUtenteTavolo(idTavolo);
				output.writeObject(s);
			}
			else if(metodo.equals("getUtenteTavolo")){
				int idTavolo=Integer.parseInt(stk.nextToken());
				Utente s=(Utente)getUtenteTavolo(idTavolo);
				output.writeObject(s);
			}
			
			
			output.close();
			client.close();
			//server.close();
			System.out.println("chiusura connessione");
			}
		
		}catch(Exception e){
			System.err.println(e);
		}
		
	}
	
	
	
	public static LinkedList<Alimento> datiPiatti(String tipoPiatto){
		LinkedList<Alimento> lista=new LinkedList<Alimento>();
		String cosaContare="select * from Piatto where tipo='"+tipoPiatto+"'";
		
		
		ResultSet rs=null;
		try{
			conn = getConnection();
			stat = conn.createStatement();
			rs=stat.executeQuery(cosaContare);
			while(rs.next()){
				Alimento a=creaAlimento(rs.getInt(1));
				lista.add(a);
			}	
		}catch(SQLException e){
			e.printStackTrace();
		}catch(IOException v){
			v.printStackTrace();
		}
		finally{
			try{
				conn.close();
				stat.close();
				rs.close();
			}catch(SQLException e){
				e.printStackTrace();
			}
		}
		return lista;
		 
	}
	
	public static Alimento creaAlimento(int codice){
		Alimento s=new Alimento();
		
		try{		
			conn = getConnection();
			stat = conn.createStatement();

			ResultSet rs = stat.executeQuery("SELECT * FROM Piatto where codice='"+codice+"'");
			while(rs.next()){
				s.setDescrizione(rs.getString(2));
				s.setNome(rs.getString(3));
				s.setTipoPiatto(rs.getString(4));
				s.setPrezzo(rs.getDouble(5));
				s.setValutazioneMedia(rs.getDouble(6));
				s.setNumeroValutazioni(rs.getInt(7));
				s.setCodificaPiatto(rs.getInt(8));
				s.setCodice(codice);
				s.setFoto(rs.getString(9));
			}
			//riempiListaIngredienti(codice);
		}catch(SQLException e){
			e.printStackTrace();
		}catch(IOException e){
			e.printStackTrace();
		}

		//conviene chiuderla
		finally{
			try {
				stat.close();
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return s;
	}
	
	
	public static boolean accendiTavolo(int i){
		s=new Utente(1);
		boolean eseguito=false;
		String accendiTavolo="update Tavolo set statoPC='ON' where idTavolo="+i;
		try{		
			conn = getConnection();
			stat = conn.createStatement();
			stat.executeUpdate(accendiTavolo);
			eseguito=true;
		}catch(SQLException s){
			s.printStackTrace();
			System.out.println("problema con il database");
		}catch(IOException e){
			e.printStackTrace();
			System.out.println("problema accendi tavolo"); 
		}
		finally{
			try{
				conn.close();
				stat.close();
			}catch(SQLException e){
				System.out.println("Errore chiusura");
			}
		}	
		return eseguito;
	}
	
	public static boolean spegniTavolo(int q){
		String spegniTavolo="update Tavolo set statoPC='OFF' where idTavolo="+q;
		String scollegaUtente="update TavoloUtente set codiceU=1 where idTavolo="+q;
		boolean eseguito=false;
		try {
			conn = getConnection();
			stat = conn.createStatement();

			stat.executeUpdate(spegniTavolo);
			stat.executeUpdate(scollegaUtente);
			eseguito=true;
		} catch (SQLException e) {
			e.printStackTrace();
		}catch(IOException e){
			e.printStackTrace();
		}
		finally{
			try {
				stat.close();
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return eseguito;
	}
	
	protected static String getData(){
		int giorno=data.get(GregorianCalendar.DAY_OF_MONTH);
		int mese=data.get(GregorianCalendar.MONTH)+1;
		int anno=data.get(GregorianCalendar.YEAR);
		String d;
		if(giorno<10 && mese<10){
			d=anno+"-0"+mese+"-0"+giorno;
		}
		else if(giorno<10 && mese>=10){
			d=anno+"-"+mese+"-0"+giorno;
		}
		else if(giorno>=10 && mese<10){
			d=anno+"-0"+mese+"-"+giorno;
		}
		else{
			d=anno+"-"+mese+"-"+giorno;
		}
		return d;
	}
	
	public static int getIdTavolo(){
		return idTavolo;
	}

	
	/*
	 * DA MODIFICARE E CNTROLLARE PERCHE' CHIUDE SEMPRE LA CONESSIONE SQL
	 * FUNZIONA COMUNQUE
	 */
	
	public static boolean inviaOrdine(int lunghezza,String lista){
		StringTokenizer st=new StringTokenizer(lista);
		
		importoDaPagare=0;
		String data=getData();
		boolean eseguito=false;
		boolean eseguito1=false;
		Ordinazione ord=new Ordinazione(getIdTavolo(),data);
		/*
		try{
			conn = getConnection();
			stat = conn.createStatement();
		}catch(SQLException e){
			e.printStackTrace();
		}catch(IOException e1){
			e1.printStackTrace();
		}
		*/
		for(int i=0;i<lunghezza;i++){
			int codice=Integer.parseInt(st.nextToken());
			Alimento a=creaAlimento(codice);
			importoDaPagare+=a.getPrezzo();
			String InserisciOrdiPiatti="insert into OrdinazionePiatto values("+ord.getCodiceOrdinazione()+","+a.getCodice()+")";
			try {
				conn = getConnection();
				stat = conn.createStatement();
				stat.executeUpdate(InserisciOrdiPiatti);
				eseguito=true;
			} catch (SQLException e) {
				eseguito=false;
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		String inserisciImporto="update Ordinazione set Importo='"+importoDaPagare+"' , Pagato='N' where codice='"+ord.getCodiceOrdinazione()+"'";
		try {
			conn = getConnection();
			stat = conn.createStatement();
			stat.executeUpdate(inserisciImporto);
			eseguito1=true;
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally{
			try{
				
				stat.close();
				conn.close();
				
			}catch(SQLException w){
				w.printStackTrace();
			}
		}
		return eseguito&&eseguito1;
	}
	
	
	public static boolean valuta(int codice,int voto){
		boolean eseguito=false;
		double [] v=getValoriValutazione(codice);
		double media=(v[0]*v[1]+voto)/(v[1]+1);
		String aggiornaPiatto="update Piatto set valutazioneMedia='"+media+"' , numeroVotazione='"+(v[1]+1)+"' where codice='"+codice+"'";
		try{
			conn = getConnection();
			stat = conn.createStatement();
			stat.executeUpdate(aggiornaPiatto);
			eseguito=true;
		}catch(SQLException e){
			e.printStackTrace();
			eseguito=false;
		}catch(IOException e){
			e.printStackTrace();
			eseguito=false;
		}
		finally{
			try{
				stat.close();
				conn.close();
			}catch(SQLException w){
				w.printStackTrace();
			}
		}
		return eseguito;
	}
	
	public static double [] getValoriValutazione(int codice){
		double[] val=new double[2];
		ResultSet r=null;
		try{
			conn = getConnection();
			stat = conn.createStatement();
			r=stat.executeQuery("select valutazioneMedia, numeroVotazione from Piatto where codice='"+codice+"'");
			while(r.next()){
				val[0]=r.getDouble(1);
				val[1]=r.getDouble(2);
				System.out.println("valutazione="+r.getDouble(1)+" numero di voti="+r.getInt(2));
			}
			
		}catch(SQLException e){
			e.printStackTrace();
		}catch(IOException e){
			e.printStackTrace();
		}
		finally{
			try{
				r.close();
				stat.close();
				conn.close();
			}catch(SQLException w){
				w.printStackTrace();
			}
		}
		return val;	
	}
	
	public static LinkedList<Alimento> CostruisciMenu(String nomeMenu){
		ResultSet rs=null;
		LinkedList<Alimento> lista=new LinkedList<Alimento>();
		try{
			conn = getConnection();
			stat = conn.createStatement();
			String trovaAlimenti="select codiceP from MenuPiatto as m, Menu as i where i.nome='"+nomeMenu+"' and m.codiceM=i.codice";
			rs=stat.executeQuery(trovaAlimenti);
			while(rs.next()){
				lista.add(creaAlimento(rs.getInt(1)));
			}
		}catch(SQLException f){
			f.printStackTrace();
		}catch(IOException n){
			n.printStackTrace();
		}
		finally{
			try{
				stat.close();
				conn.close();
				rs.close();
			}catch(SQLException d){
				d.printStackTrace();
			}
		}
		return lista;
	}
	
	public static LinkedList<Alimento> RandomMenu(){
		LinkedList<Alimento> [] menu=new LinkedList[3];
		LinkedList<Alimento> rest=new LinkedList<Alimento>();
		ResultSet rs=null;

		//CREAZIONE DELLE LINKEDLIST
		for(int i=0;i<menu.length;i++){
			menu[i]=new LinkedList<Alimento>();
		}

		//RIEMPIMENTO DELLE LINKEDLIST CON I MIGLIORI 5 PIATTI DI OGNI PORTATA
		for(int i=0;i<menu.length;i++){
			String selezionaMenu="Select codice from Piatto where codificaTipo='"+(i+1)+"' ORDER BY valutazioneMedia DESC LIMIT 5";
			try{
				conn = getConnection();
				stat = conn.createStatement();	
				rs=stat.executeQuery(selezionaMenu);
				while(rs.next()){
					menu[i].add(creaAlimento(rs.getInt(1)));
				}
			}catch(SQLException c){
				c.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			finally{
				try{
					stat.close();
					conn.close();
					rs.close();
				}catch(SQLException d){
					d.printStackTrace();
				}
			}
		}
		//SELEZIONE DI UNO TRA I MIGLIORI 5 IN MANIERA RANDOM
		for(int i=0;i<menu.length;i++){
			Random r=new Random();
			int casuale=r.nextInt(menu.length);
			rest.add(menu[i].get(casuale));
		}
		return rest;
	}

	public static int contaPiatto(String tipoPiatto){
		ResultSet rs=null;
		int contatore=0;
		try{
			conn = getConnection();
			stat = conn.createStatement();
			String cosaContare="select * from Piatto where tipo='"+tipoPiatto+"'";
			System.out.println("AAAAAAAAAA    "+cosaContare);
			rs=stat.executeQuery(cosaContare);
			while(rs.next()){
				contatore++;
			}
		}catch(SQLException e){
			e.printStackTrace();
		}catch(IOException ee){
			ee.printStackTrace();
		}
		finally{
			try{
				conn.close();
				stat.close();
				rs.close();
			}catch(SQLException e){
				e.printStackTrace();
			}
		}
		return contatore;
	}

	public static int contaQuantiMenu(){
		int cont=0;
		ResultSet rs=null;
		try{
			conn = getConnection();
			stat = conn.createStatement();
			String conta="select tipo from Menu";
			rs=stat.executeQuery(conta);
			while(rs.next())
				cont++;
		}catch(SQLException e){
			e.printStackTrace();
		}catch(IOException e){
			e.printStackTrace();
		}
		finally{
			try{
				conn.close();
				stat.close();
				rs.close();
			}catch(SQLException e){
				e.printStackTrace();
			}
		}
		return cont;
	}
	
	public static int getNumeroPosti (int e){
		int p=0;
		String a="select numeroPosti from Tavolo where idTavolo="+e;
		ResultSet rs=null;
		try{
			conn = getConnection();
			stat = conn.createStatement();
			rs=stat.executeQuery(a);
			while(rs.next()){
				p=rs.getInt(1);
			}	
		}catch(SQLException eq){
			eq.printStackTrace();
		}catch(IOException d){
			d.printStackTrace();
		}
		finally{
			try{
				conn.close();
				stat.close();
				rs.close();
			}catch(SQLException ew){
				ew.printStackTrace();
			}
		}

		return p;

	}

	public static double getImportoDaPagare(int idTavolo){
		double imp=0;
		char c='u';
		String quantoPagano="select Importo, Pagato from Ordinazione where idTavolo='"+idTavolo+"' order by codice desc limit 1";
		ResultSet rs=null;
		try{
			conn = getConnection();
			stat = conn.createStatement();
			rs=stat.executeQuery(quantoPagano);
			while(rs.next()){
				imp=rs.getDouble(1);
				c=rs.getString(2).charAt(0);
			}

		}catch(SQLException e){
			e.printStackTrace();
		}catch(IOException w){
			w.printStackTrace();
		}
		finally{
			try{
				conn.close();
				stat.close();
				rs.close();
			}catch(SQLException ew){
				ew.printStackTrace();
			}
		}
		if(c=='S'){
			imp=0;
		}
		return imp;
	}

	public static int getCodiceU(String nick){
		String ut="select codiceU  from Utenti where nick='"+nick+"'";
		int c=0;
		ResultSet rs=null;
		try{
			conn = getConnection();
			stat = conn.createStatement();
			rs=stat.executeQuery(ut);
			while(rs.next())
				c=rs.getInt(1);
		}catch(SQLException e){
			e.printStackTrace();
		}catch(IOException w){
			w.printStackTrace();
		}

		finally{
			try{
				conn.close();
				stat.close();
				rs.close();
			}catch(SQLException ew){
				ew.printStackTrace();
			}
		}
		return c;
	}

	public static boolean dissociaUtenteTavolo(int c){
		boolean eseguito=false;
		String scollegaUtente="update TavoloUtente set codiceU=1 where idTavolo="+c;
		try {
			conn = getConnection();
			stat = conn.createStatement();
			stat.executeUpdate(scollegaUtente);
			eseguito=true;
		} catch (SQLException e) {
			e.printStackTrace();
		}catch(IOException e){
			e.printStackTrace();
		}
		finally{
			try {
				stat.close();
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		} 
		return eseguito;
	}
	
	public static boolean associaUtenteATavolo(String nick,int idTavolo){
		boolean eseguito=false;
		Utente s1=new Utente(nick,"");
		int c=getCodiceU(nick);
		String f="update TavoloUtente set codiceU="+c+" where idTavolo="+idTavolo;
		try{
			conn = getConnection();
			stat = conn.createStatement();
			stat.executeUpdate(f);
			eseguito=true;
			System.out.print("!!!!"+s1.getNick()+"!!!!");
			
		}catch(SQLException e){
			e.printStackTrace();
		}catch(IOException w){
			w.printStackTrace();
		}
		finally{
			try{
				conn.close();
				stat.close();
			}catch(SQLException ew){
				ew.printStackTrace();
			}
		}
		return eseguito;
	}
	
	public static int getIdUtenteTavolo(int idTavolo){
		String ut="select codiceU  from TavoloUtente where idTavolo="+idTavolo;
		int c=0;
		ResultSet rs=null;
		try {
			conn = getConnection();
			stat = conn.createStatement();
			rs = stat.executeQuery(ut);
			while(rs.next())
				c=rs.getInt(1);	
		} catch (SQLException e) {
			e.printStackTrace();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		finally{
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return c;
	}
	public Utente creaUtente(int idUtente){
		Utente ritorno=null;
		
		
		
		
		
		
		return ritorno;
	}
	public static Utente getUtenteTavolo(int idUtente){
		Utente zx=null;
		ResultSet rs=null;
		String n=null;
		String prendiUtente="select * from Utenti where codiceU="+idUtente;
		try {
			conn = getConnection();
			stat = conn.createStatement();
			rs = stat.executeQuery(prendiUtente);
			while(rs.next()){
				n=rs.getString(6);
			}
			zx=new Utente(n,"");
		} catch (SQLException e) {
			e.printStackTrace();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		
		finally{
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		System.out.println(zx);
		return zx;	
	}
	
	
	public static Connection getConnection() throws SQLException, IOException{  
		Properties props = new Properties();
		FileInputStream in = new FileInputStream("database.properties");
		props.load(in);
		in.close();

		String drivers = props.getProperty("jdbc.drivers");
		String url = props.getProperty("jdbc.url");
		String username = props.getProperty("jdbc.username");
		String password = props.getProperty("jdbc.password");

		if (drivers != null)
			System.setProperty("jdbc.drivers", drivers);

		return DriverManager.getConnection(url, username, password);
	}

}
